/**
 * 测试死锁的两种模式，1是循环加锁，2是两个线程,各自持有一把锁,请求另一把
 * @author: sundx
 * @date: 2020-05-27 16:50:00
 * @Last Modified by: sundx
 * @Last Modified time: 2020-05-27 21:06:48
 */
#include <iostream>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
int counter1 = 100;
int counter2 = 200;

void *get1want2(void *);
void *get2want1(void *);

int main() {
  pthread_t tid;
  int ret;
  ret = pthread_create(&tid, nullptr, get1want2, nullptr);
  if (ret < 0) {
    std::cout << "pthread_create failed " << strerror(ret) << std::endl;
  }
  ret = pthread_create(&tid, nullptr, get2want1, nullptr);
  if (ret < 0) {
    std::cout << "pthread_create failed " << strerror(ret) << std::endl;
  }
  for (int i = 0; i < 2; ++i) {
    ret = pthread_join(tid, nullptr);
    if (ret < 0) {
      std::cout << "pthread_join failed " << strerror(ret) << std::endl;
    }
  }

  ret = pthread_mutex_destroy(&mutex1);
  if (ret < 0) {
    std::cout << "pthread_destroy failed " << strerror(ret) << std::endl;
  }
  ret = pthread_mutex_destroy(&mutex2);
  if (ret < 0) {
    std::cout << "pthread_destroy failed " << strerror(ret) << std::endl;
  }
  pthread_exit(nullptr);
  return 0;
}

void *get1want2(void *argv) { // 锁了1 想去锁2
  pthread_mutex_lock(&mutex1);
  std::cout << pthread_self() << " 1: " << counter1 << std::endl;
  pthread_mutex_lock(&mutex2);
  std::cout << pthread_self() << " 2: " << counter2 << std::endl;
  sleep(1);
  pthread_mutex_unlock(&mutex2);
  pthread_mutex_unlock(&mutex1);

  return nullptr;
}
void *get2want1(void *argv) { // 锁了2 想去锁1
  pthread_mutex_lock(&mutex2);
  std::cout << pthread_self() << " 2: " << counter2 << std::endl;
  pthread_mutex_lock(&mutex1);
  std::cout << pthread_self() << " 1: " << counter1 << std::endl;
  sleep(1);
  pthread_mutex_unlock(&mutex1);
  pthread_mutex_unlock(&mutex2);

  return nullptr;
}